/*************************************************************************
Parsing UART commands exemple

based on www.adnbr.co.uk/articles/parsing-simple-usart-commands

uses Peter Fleury's uart library http://homepage.hispeed.ch/peterfleury/avr-software.html#libs
for easier microcontroler change.
*************************************************************************/


#include "uartcmd.h"

#define TRUE 1
#define FALSE 0
#define CHAR_NEWLINE '\n'
#define CHAR_RETURN '\r'
#define RETURN_NEWLINE "\r\n"

void copy_command(void);
void process_commands(void);
void print_value (char *id, int value);
void uart_ok(void);
int parse_assignment (char input[16]);
void process_uart(void);

unsigned char data_count = 0;
unsigned char data_in[8];
char command_in[8];
int kpl = 15; //user modifiable variable
float kil = 0.1; //user modifiable variable
float kdl = 220; //user modifiable variable
int kpr = 15; //user modifiable variable
float kir = 0.4; //user modifiable variable
float kdr = 200; //user modifiable variable
int run=1;
volatile int show=1;
volatile int start=1;
volatile int stop=1;

int parse_assignment (char input[16]) {
  char *pch;
  char cmdValue[16];
  // Find the position the equals sign is
  // in the string, keep a pointer to it
  pch = strchr(input, '=');
  // Copy everything after that point into
  // the buffer variable
  strcpy(cmdValue, pch+1);
  // Now turn this value into an integer and
  // return it to the caller.
  return atoi(cmdValue);
}

void copy_command () {
  // Copy the contents of data_in into command_in
  memcpy(command_in, data_in, 8);
  // Now clear data_in, the UART can reuse it now
  memset(data_in, 0, 8);
}

void process_commands() {

  if(strcasestr(command_in,"KPL") != NULL){
    if(strcasestr(command_in,"?") != NULL)
      print_value("kpl", kpl);
    else
      kpl = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"KIL") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
		print_value("kil", kil);
	  else
		kil = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"KDL") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
		print_value("kdl", kdl);
	  else
		kdl = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"KPR") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
		print_value("kpr", kpr);
	  else
		kpr = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"KIR") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
		print_value("kir", kir);
	  else
		kir = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"KDR") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
		print_value("kdr", kdr);
	  else
		kdr = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"RUN") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
	  print_value("run", run);
	  else
	  run = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"START") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
	  print_value("start", start);
	  else
	  start = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"STOP") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
	  print_value("stop", stop);
	  else
	  stop = parse_assignment(command_in);
  }
  else if(strcasestr(command_in,"SHOW") != NULL){
	  if(strcasestr(command_in,"?") != NULL)
	  print_value("show", show);
	  else
	  show = parse_assignment(command_in);
  }
  else {
	  if (strcasestr(command_in,"") != NULL)
		uart_puts("NOTHING ");
  }
} 

void print_value (char *id, int value) {
  char buffer[8];
  itoa(value, buffer, 10);
  uart_puts(id);
  uart_putc('=');
  uart_puts(buffer);
  uart_puts(RETURN_NEWLINE);
}

void uart_ok() {
  uart_puts("DONE");
  uart_puts(RETURN_NEWLINE);
}

void process_uart(){
  /* Get received character from ringbuffer
   * uart_getc() returns in the lower byte the received character and 
   * in the higher byte (bitmask) the last receive error
   * UART_NO_DATA is returned when no data is available.   */
  unsigned int c = uart_getc();
  
  if ( c & UART_NO_DATA ){
    // no data available from UART 
  }
  else {
    // new data available from UART check for Frame or Overrun error
    if ( c & UART_FRAME_ERROR ) {
      /* Framing Error detected, i.e no stop bit detected */
      uart_puts_P("UART Frame Error: ");
    }
    if ( c & UART_OVERRUN_ERROR ) {
      /* Overrun, a character already present in the UART UDR register was 
       * not read by the interrupt handler before the next character arrived,
       * one or more received characters have been dropped */
      uart_puts_P("UART Overrun Error: ");
    }
    if ( c & UART_BUFFER_OVERFLOW ) {
      /* We are not reading the receive buffer fast enough,
       * one or more received character have been dropped  */
      uart_puts_P("Buffer overflow error: ");
    }
    
    // Add char to input buffer
    data_in[data_count] = c;
    
    // Return is signal for end of command input
    if (data_in[data_count] == CHAR_RETURN) {
      // Reset to 0, ready to go again
      data_count = 0;
      uart_puts(RETURN_NEWLINE);
      
      copy_command();
      process_commands();
      uart_ok();
    } 
    else {
      data_count++;
    }
    
    uart_putc( (unsigned char)c );
  }
}

